package fn;

import java.io.Serializable;

public abstract class Function implements Comparable<Function>, Serializable {
	private static final long serialVersionUID = -8634026065988460665L;

	private String name;

	protected Function() {}

	protected abstract Function[] child();

	public abstract double evaluate(double sub);

	public abstract String prefix();

	public abstract String infix();

	public abstract String postfix();

	protected abstract boolean withPar();

	public String toLatex() {
		String out = prefix();
		if (child() != null) {
			for (Function fn : child()) {
				if (this.compareTo(fn) > 0)
					out += "( " + fn.toLatex() + " )";
				else
					out += fn.toLatex();
				out += infix();
			}
			out = out.substring(0, out.length() - infix().length());
		}
		return out + postfix();
	}

	@Override
	public String toString() {
		return name;
	}

	public Function setName(String name) {
		this.name = name;
		return this;
	}

	@Override
	public int compareTo(Function fn) {
		return precedence() - fn.precedence();
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof Function)
			return ((Function) o).toLatex().trim().equals(toLatex().trim());
		return false;
	}

	protected abstract int precedence();

	public abstract Function derivative();

	public static Function parse(String in) {
		Parser p = new Parser();
		return p.parse(in.replaceAll(" ", ""));
	}
}
